package net.jxtz.jxtzos.authentication;


import lombok.extern.slf4j.Slf4j;
import org.checkerframework.checker.units.qual.A;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.security.authentication.AuthenticationProvider;
import org.springframework.security.authentication.AuthenticationServiceException;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.stereotype.Component;

/**
 *
 * 自定义用户认证处理逻辑类
 *
 * @author a123
 */
@Slf4j
@Component
public class MyAuthenticationProvider implements AuthenticationProvider {

    /**
     *
     * 处理校验逻辑
     *
     * @param authentication 封装了用户在前端传回来的用户信息
     * @return 完整的校验成功对象
     * @throws AuthenticationException 校验异常
     */
    @Override
    public Authentication authenticate(Authentication authentication) throws AuthenticationException {
        log.info("进入用户信息检验逻辑");
        // 获取用户输入的用户名和密码
        String userName = authentication.getName();
        // getCredentials() 返回的就是在前端传入的用户密码
        String password = authentication.getCredentials().toString();
        // 获取已经封装的用户信息
        final UserDetails userDetails = myUserDetailServiceImpl.loadUserByUsername(userName);
        // 密码校验
        boolean matches = bCryptPasswordEncoder.matches(password, userDetails.getPassword());
        if (matches){
            // 校验通过，封装进校验对象
            log.info("用户信息校验成功");
            return new UsernamePasswordAuthenticationToken(userDetails, password, userDetails.getAuthorities());
        }else {
            // 校验失败
            log.info("用户信息校验失败");
            throw new AuthenticationServiceException("校验失败");
        }
    }

    @Override
    public boolean supports(Class<?> aClass) {
        return true;
    }

    private MyUserDetailServiceImpl myUserDetailServiceImpl;

    private BCryptPasswordEncoder bCryptPasswordEncoder;

    @Autowired
    public void setMyUserDetailServiceImpl(MyUserDetailServiceImpl myUserDetailServiceImpl){
        this.myUserDetailServiceImpl = myUserDetailServiceImpl;
    }

    @Autowired
    public void setbCryptPasswordEncoder(BCryptPasswordEncoder bCryptPasswordEncoder){
        this.bCryptPasswordEncoder = bCryptPasswordEncoder;
    }
}
